#!/usr/bin/env node

/**
 * 生成pages类型定义工具
 * 基于pagesSchema.js和pagesSchemaUniAppx.json生成TypeScript类型定义
 */

const fs = require('fs');
const path = require('path');

// 路径配置
const rootDir = path.resolve(__dirname, '..');
const pagesSchemaPath = path.join(rootDir, 'schemas/pagesSchema.js');
const pagesSchemaUniAppxPath = path.join(rootDir, 'schemas/pagesSchemaUniAppx.json');
const outputPath = path.join(rootDir, 'src', 'types', 'pages.ts');

// 读取schema文件
async function readSchemaFiles() {
    try {
        // 读取并解析pagesSchema.js (ES模块)
        const pagesSchemaContent = fs.readFileSync(pagesSchemaPath, 'utf8');
        // 提取JSON对象部分（去掉 export const PagesSchema = 部分）
        const jsonStr = pagesSchemaContent.replace(/export\s+const\s+PagesSchema\s*=\s*/, '');
        const pagesSchema = eval(`(${jsonStr})`);

        // 读取并解析pagesSchemaUniAppx.json文件
        const pagesSchemaUniAppx = JSON.parse(fs.readFileSync(pagesSchemaUniAppxPath, 'utf8'));

        return {pagesSchema, pagesSchemaUniAppx};
    } catch (error) {
        console.error('读取schema文件失败:', error);
        process.exit(1);
    }
}

// 处理注释，优先使用uniAppx版本的描述
function extractDescription(property, uniAppxProperty) {
    if (!property) return '';

    // 优先使用uniAppx中的描述
    let description = '';
    if (uniAppxProperty && uniAppxProperty.description) {
        description = uniAppxProperty.description;
    } else if (uniAppxProperty && uniAppxProperty.markdownDescription) {
        // 如果有markdownDescription，优先使用它（完全保留原始格式）
        description = uniAppxProperty.markdownDescription;
    } else if (property.description) {
        description = property.description;
    }

    // 不再添加默认值

    return description;
}

// 从属性名获取可能的枚举类型名
function getEnumTypeNameFromPropName(propName) {
    if (!propName) return null;

    // 一般命名规则
    if (propName.toLowerCase().includes('type')) {
        return propName.charAt(0).toUpperCase() + propName.slice(1);
    } else {
        return `${propName.charAt(0).toUpperCase() + propName.slice(1)}Type`;
    }
}

// 处理类型，根据属性特征自动匹配枚举类型
function mapJsonSchemaTypeToTs(property, propName, enumTypes, defName, customStringTypes, generatedInterfaces) {
    if (!property) return 'any';

    // 处理 patternProperties（如 preloadRule）
    if (property.patternProperties) {
        const patternKeys = Object.keys(property.patternProperties);
        if (patternKeys.length > 0) {
            const patternProperty = property.patternProperties[patternKeys[0]];
            if (patternProperty.$ref) {
                const refType = patternProperty.$ref.replace('#/definitions/', '');
                return `Record<string, ${refType}>`;
            }
        }
        return 'Record<string, any>';
    }

    // 处理有properties的对象类型 - 动态生成接口
    if (property.type === 'object' && property.properties && propName) {
        const interfaceName = propName.charAt(0).toUpperCase() + propName.slice(1) + 'Options';
        // 记录需要生成的接口
        if (!generatedInterfaces.has(interfaceName)) {
            generatedInterfaces.set(interfaceName, {
                properties: property.properties,
                description: property.description || property.markdownDescription || `${propName}配置选项`
            });
        }
        return interfaceName;
    }

    // 处理枚举类型
    if (property.enum && Array.isArray(property.enum)) {
        // 尝试找到匹配的枚举类型
        const possibleTypeName = getEnumTypeNameFromPropName(propName);
        if (enumTypes.has(possibleTypeName)) {
            return possibleTypeName;
        }

        // 否则生成字面量联合类型
        return property.enum.map(item => `'${item}'`).join(' | ');
    }

    // 处理联合类型
    if (Array.isArray(property.type)) {
        return property.type
            .map(type => {
                if (type === 'string') return 'string';
                if (type === 'number') return 'number';
                if (type === 'boolean') return 'boolean';
                if (type === 'object') return 'Record<string, any>';
                if (type === 'array') return 'any[]';
                if (type.startsWith('string.')) {
                    // 处理自定义字符串类型，直接使用自定义类型
                    const customType = type.replace('string.', '');
                    // 确保添加这个自定义类型到集合中
                    if (customType && !customStringTypes.has(customType)) {
                        customStringTypes.add(customType);
                    }
                    return customType;
                }
                return 'any';
            })
            .join(' | ');
    }

    // 处理引用类型
    if (property.$ref) {
        return property.$ref.replace('#/definitions/', '');
    }

    // 基本类型映射
    switch (property.type) {
        case 'string':
            // 如果有format属性，这可能是自定义字符串类型
            if (property.format) {
                const customType = property.format.charAt(0).toUpperCase() + property.format.slice(1) + 'String';
                if (!customStringTypes.has(customType)) {
                    customStringTypes.add(customType);
                }
                return customType;
            }
            return 'string';
        case 'number':
            return 'number';
        case 'boolean':
            return 'boolean';
        case 'object':
            return 'Record<string, any>';
        case 'array':
            if (property.items && property.items.$ref) {
                return `${property.items.$ref.replace('#/definitions/', '')}[]`;
            }
            if (property.items && property.items.type) {
                // 处理数组元素的类型
                if (Array.isArray(property.items.type)) {
                    const itemTypes = property.items.type.map(type => {
                        if (type.startsWith('string.')) {
                            const customType = type.replace('string.', '');
                            if (customType && !customStringTypes.has(customType)) {
                                customStringTypes.add(customType);
                            }
                            return customType;
                        }
                        return type;
                    }).join(' | ');
                    return `(${itemTypes})[]`;
                } else {
                    return `${property.items.type}[]`;
                }
            }
            return 'any[]';
        default:
            return 'any';
    }
}

// 收集并生成枚举类型（优先使用uniAppx的描述）
function collectEnumTypes(definitions, uniAppxDefs) {
    const enumTypes = new Map();

    // 第一遍扫描：收集所有枚举类型
    for (const [defName, defSchema] of Object.entries(definitions)) {
        if (defSchema.properties) {
            for (const [propName, propSchema] of Object.entries(defSchema.properties)) {
                if (propSchema.enum && Array.isArray(propSchema.enum)) {
                    // 生成枚举类型名称
                    let typeName = getEnumTypeNameFromPropName(propName);

                    // 避免重复添加相同的枚举类型
                    if (!enumTypes.has(typeName)) {
                        // 获取描述信息，优先使用uniAppx中的描述
                        let description = '';
                        let enumDescriptions = {};
                        let markdownDescription = '';

                        if (uniAppxDefs && uniAppxDefs[defName] && uniAppxDefs[defName].properties &&
                            uniAppxDefs[defName].properties[propName]) {
                            const uniAppxProp = uniAppxDefs[defName].properties[propName];

                            // 优先使用markdownDescription，然后是description
                            if (uniAppxProp.markdownDescription) {
                                markdownDescription = uniAppxProp.markdownDescription;
                                description = uniAppxProp.markdownDescription; // 直接使用原始markdownDescription，不做任何处理
                            } else if (uniAppxProp.description) {
                                description = uniAppxProp.description;
                            } else {
                                description = propSchema.description || `${propName}类型`;
                            }

                            // 获取枚举值的描述
                            if (uniAppxProp.enumDescriptions) {
                                enumDescriptions = uniAppxProp.enumDescriptions;
                            }
                        } else {
                            description = propSchema.description || `${propName}类型`;
                        }

                        // 保存枚举类型定义
                        enumTypes.set(typeName, {
                            description: description,
                            values: propSchema.enum,
                            type: propSchema.enum.map(v => `'${v}'`).join(' | ')
                        });
                    }
                }
            }
        }
    }

    return enumTypes;
}

// 生成枚举类型定义（使用更详细的注释）
function generateEnumTypesDefinitions(enumTypes) {
    let result = '';

    for (const [typeName, info] of enumTypes.entries()) {
        result += `/**\n * ${info.description}\n */\n`;
        result += 'export type ' + typeName + ' = ' + info.type + ';\n\n';
    }

    return result;
}

// 收集属性中定义的自定义字符串类型
function collectCustomStringTypes(schema) {
    const customTypes = new Set();

    // 递归扫描所有属性
    function scanProperties(properties) {
        if (!properties) return;

        for (const [propName, propSchema] of Object.entries(properties)) {
            // 处理复合类型
            if (Array.isArray(propSchema.type)) {
                for (const type of propSchema.type) {
                    if (typeof type === 'string' && type.startsWith('string.')) {
                        const customType = type.replace('string.', '');
                        customTypes.add(customType);
                    }
                }
            }

            // 处理format属性
            if (propSchema.type === 'string' && propSchema.format) {
                const customType = propSchema.format.charAt(0).toUpperCase() + propSchema.format.slice(1) + 'String';
                customTypes.add(customType);
            }

            // 递归处理嵌套对象
            if (propSchema.properties) {
                scanProperties(propSchema.properties);
            }

            // 处理数组项
            if (propSchema.type === 'array' && propSchema.items && propSchema.items.properties) {
                scanProperties(propSchema.items.properties);
            }
        }
    }

    // 扫描根级属性
    if (schema.properties) {
        scanProperties(schema.properties);
    }

    // 扫描definitions中的所有属性
    if (schema.definitions) {
        for (const defSchema of Object.values(schema.definitions)) {
            if (defSchema.properties) {
                scanProperties(defSchema.properties);
            }
        }
    }

    return customTypes;
}

// 生成自定义字符串类型定义
function generateCustomStringTypesDefinitions(customTypes) {
    let result = '';

    // 为每个自定义类型生成定义
    for (const typeName of customTypes) {
        const description = typeName;
        result += `/**\n * ${description}\n */\n`;
        result += `export type ${typeName} = string;\n\n`;
    }

    return result;
}

// 生成接口属性定义
function generateInterfaceProperties(properties, required = [], enumTypes, uniAppxProps = {}, defName, customStringTypes, generatedInterfaces) {
    if (!properties) return '';

    let result = '';

    for (const [propName, propSchema] of Object.entries(properties)) {
        // 获取uniAppx中的属性信息
        const uniAppxProp = uniAppxProps[propName];

        // 获取描述，不再获取平台信息
        const description = extractDescription(propSchema, uniAppxProp);

        const isRequired = required.includes(propName);
        const propType = mapJsonSchemaTypeToTs(propSchema, propName, enumTypes, defName, customStringTypes, generatedInterfaces);

        if (description) {
            result += '  /**\n';
            result += `   * ${description}\n`;
            result += '   */\n';
        }

        // 处理属性名，如果包含特殊字符（连字符等），则使用双引号包裹
        const formattedPropName = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(propName)
            ? propName
            : `"${propName}"`;

        result += `  ${formattedPropName}${isRequired ? '' : '?'}: ${propType};\n\n`;
    }

    return result;
}

// 合并Schema定义，保留两边的信息
function mergeSchemaDefinitions(pagesSchema, pagesSchemaUniAppx) {
    const result = {...pagesSchema};

    // 合并definitions
    if (result.definitions && pagesSchemaUniAppx.definitions) {
        for (const defName in result.definitions) {
            if (pagesSchemaUniAppx.definitions[defName]) {
                // 合并required属性
                if (pagesSchemaUniAppx.definitions[defName].required) {
                    result.definitions[defName].required = pagesSchemaUniAppx.definitions[defName].required;
                }

                // 合并属性的平台信息和描述
                if (result.definitions[defName].properties && pagesSchemaUniAppx.definitions[defName].properties) {
                    for (const propName in result.definitions[defName].properties) {
                        if (pagesSchemaUniAppx.definitions[defName].properties[propName]) {
                            // 将uniPlatform信息添加到属性中
                            result.definitions[defName].properties[propName].uniPlatform =
                                pagesSchemaUniAppx.definitions[defName].properties[propName].uniPlatform;

                            // 合并描述信息和默认值
                            if (pagesSchemaUniAppx.definitions[defName].properties[propName].description) {
                                result.definitions[defName].properties[propName].uniAppxDescription =
                                    pagesSchemaUniAppx.definitions[defName].properties[propName].description;
                            }

                            if (pagesSchemaUniAppx.definitions[defName].properties[propName].markdownDescription) {
                                result.definitions[defName].properties[propName].markdownDescription =
                                    pagesSchemaUniAppx.definitions[defName].properties[propName].markdownDescription;
                            }

                            if (pagesSchemaUniAppx.definitions[defName].properties[propName].defaultValue) {
                                result.definitions[defName].properties[propName].defaultValue =
                                    pagesSchemaUniAppx.definitions[defName].properties[propName].defaultValue;
                            }

                            // 合并枚举值描述
                            if (pagesSchemaUniAppx.definitions[defName].properties[propName].enumDescriptions) {
                                result.definitions[defName].properties[propName].enumDescriptions =
                                    pagesSchemaUniAppx.definitions[defName].properties[propName].enumDescriptions;
                            }
                        }
                    }
                }
            }
        }
    }

    return result;
}

// 生成类型定义文件
async function generateTypesFile() {
    const {pagesSchema, pagesSchemaUniAppx} = await readSchemaFiles();

    // 合并Schema
    const mergedSchema = mergeSchemaDefinitions(pagesSchema, pagesSchemaUniAppx);

    // 收集自定义字符串类型
    const customStringTypes = collectCustomStringTypes(mergedSchema);

    // 收集枚举类型（使用合并后的Schema）
    const enumTypes = collectEnumTypes(mergedSchema.definitions, pagesSchemaUniAppx.definitions);

    // 用于收集动态生成的接口
    const generatedInterfaces = new Map();

    let typesFileContent = `/**
 * 页面配置类型定义
 * 此文件由脚本自动生成，请勿手动修改
 */

`;

    // 添加自定义字符串类型定义
    typesFileContent += generateCustomStringTypesDefinitions(customStringTypes);

    // 添加枚举类型定义
    typesFileContent += generateEnumTypesDefinitions(enumTypes);

    // 处理pagesSchema的definitions
    for (const [defName, defSchema] of Object.entries(mergedSchema.definitions)) {
        if (defSchema.type === 'object') {
            typesFileContent += `/**
 * ${defName} 接口定义
 */
export interface ${defName} {\n`;

            const required = defSchema.required || [];
            const uniAppxProps = pagesSchemaUniAppx.definitions[defName]?.properties || {};
            typesFileContent += generateInterfaceProperties(defSchema.properties, required, enumTypes, uniAppxProps, defName, customStringTypes, generatedInterfaces);

            typesFileContent += `}\n\n`;
        }
    }

    // 处理主接口并收集需要生成的动态接口
    let mainInterfaceContent = '';
    const pagesOptionsRequired = pagesSchemaUniAppx.required || [];
    const uniAppxRootProps = pagesSchemaUniAppx.properties || {};
    mainInterfaceContent += generateInterfaceProperties(mergedSchema.properties, pagesOptionsRequired, enumTypes, uniAppxRootProps, 'root', customStringTypes, generatedInterfaces);

    // 生成动态收集的接口
    for (const [interfaceName, interfaceInfo] of generatedInterfaces.entries()) {
        typesFileContent += `/**
 * ${interfaceInfo.description}
 */
export interface ${interfaceName} {\n`;
        
        // 获取对应的uniAppx属性信息
        const correspondingPropName = interfaceName.replace('Options', '').toLowerCase();
        const uniAppxInterfaceProps = uniAppxRootProps[correspondingPropName]?.properties || {};
        
        typesFileContent += generateInterfaceProperties(
            interfaceInfo.properties, 
            [], // 动态接口通常没有required字段
            enumTypes, 
            uniAppxInterfaceProps, 
            interfaceName, 
            customStringTypes, 
            new Map() // 避免嵌套循环
        );
        
        typesFileContent += `}\n\n`;
    }

    // 添加主接口
    typesFileContent += `/**
 * pages.json 配置选项
 */
export interface PagesOptions {\n`;

    typesFileContent += mainInterfaceContent;
    typesFileContent += `}\n`;

    // 写入文件
    try {
        fs.writeFileSync(outputPath, typesFileContent);
        console.log(`TypeScript类型定义已生成: ${outputPath}`);
    } catch (error) {
        console.error('生成类型文件失败:', error);
        process.exit(1);
    }
}

// 执行生成
generateTypesFile().catch(err => {
    console.error('执行出错:', err);
    process.exit(1);
});
